package id.co.shuba.spamobile.task;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import id.co.shuba.spamobile.App;
import id.co.shuba.spamobile.Encryptor;
import id.co.shuba.spamobile.WSException;
import id.co.shuba.spamobile.data.DSARDB;
import id.co.shuba.spamobile.data.DatabaseHandler;
import id.co.shuba.spamobile.data.MaintenanceVisitDB;
import id.co.shuba.spamobile.data.StandardDB;
import id.co.shuba.spamobile.data.ProspectDB;
import id.co.shuba.spamobile.data.ProspectProgressDB;
import id.co.shuba.spamobile.model.UserInfo;
import id.co.shuba.spamobile.services.WebServiceHelper;
import id.co.shuba.spamobile.util.Base64;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.view.SurfaceView;

public class UploadProspectTask extends BaseProgressTask {
	WebServiceHelper _ws;
	DatabaseHandler _db;
	UserInfo _user;
	String _imei;
	INotify _notify;

	public UploadProspectTask(WebServiceHelper ws, DatabaseHandler db, INotify notify, UserInfo user, String imei) {
		_ws = ws;
		_db = db;
		_user = user;
		_imei = imei;
		_notify = notify;
	}	
	
	private JSONArray Upload(ArrayList<JSONObject> list, String methodName) throws Exception {
		Encryptor enc = new Encryptor(
				Encryptor.ENC_AES,
				Encryptor.ENC_AES, App.createCompleteKey(_user.getEncryptionKey()), App.IV);
		String pwd = enc.decryptText(_user.getPassword());	
		
		Map<String, Object> properties = new HashMap<String, Object>();								
		JSONArray array = new JSONArray(list);								
		String data = Base64.encodeBytes(array.toString().getBytes(), Base64.GZIP);						
		properties.put("data", data);					
		properties.put("nip", _user.getNip());
		properties.put("password", pwd);
		properties.put("imei", _imei);
		properties.put("token", _user.getToken());
		
		String result = _ws.Call(methodName, properties).toString();
		
		String strJSON = new String(Base64.decode(result, Base64.GZIP)); 			
		publishProgress(30);			
		
		JSONObject res = new JSONObject(strJSON);
		String error = res.getString("error");
		if (error.length() > 0 && !error.equals("null"))
			throw new WSException(error);
			
		JSONArray jsonArray = res.getJSONArray("result");	
		return jsonArray;
	}

	@Override
	protected AsyncTaskResult<Void> doInBackground(Object... params) {
		try {					
			publishStatus("Uploading...");						
			
			ProspectDB mv = new ProspectDB(_db);
			Cursor cursor = mv.getListExport(_user.getAoCode());
			ArrayList<JSONObject> list = new ArrayList<JSONObject>();		
			if (cursor.moveToFirst()) {
				int length = cursor.getCount();
				int step = (int)Math.ceil((double)(length/App.MAX_ROW_UPLOAD));
				
				int numStep = 1;				
				int i = 0;
				do {				
					JSONObject obj = new JSONObject();	
					obj.put("prospectID", cursor.getString(cursor.getColumnIndex("PROSPECT_ID")));
					obj.put("prospectNo", cursor.getString(cursor.getColumnIndex("PROSPECT_NO")));
					obj.put("fullName", cursor.getString(cursor.getColumnIndex("FULL_NAME")));
					obj.put("jenisUsaha", cursor.getString(cursor.getColumnIndex("JENIS_USAHA")));
					obj.put("rencanaPlafon", cursor.getLong(cursor.getColumnIndex("RENCANA_PLAFON")));
					obj.put("mobilePhone", cursor.getString(cursor.getColumnIndex("MOBILE_PHONE")));
					obj.put("officePhone", cursor.getString(cursor.getColumnIndex("OFFICE_PHONE")));
					obj.put("residentialPhone", cursor.getString(cursor.getColumnIndex("RESIDENTIAL_PHONE")));
					obj.put("kodyaKabBusiness", cursor.getString(cursor.getColumnIndex("KODYA_KAB_BUSINESS")));
					obj.put("kecamatanBusiness", cursor.getString(cursor.getColumnIndex("KECAMATAN_BUSINESS")));
					obj.put("kelurahanBusiness", cursor.getString(cursor.getColumnIndex("KELURAHAN_BUSINESS")));
					obj.put("prospectType", cursor.getString(cursor.getColumnIndex("PROSPECT_TYPE")));
					obj.put("debtorType", cursor.getString(cursor.getColumnIndex("DEBTOR_TYPE")));
					obj.put("channeling", cursor.getString(cursor.getColumnIndex("CHANNELING")));
					obj.put("zipCodeBusiness", cursor.getString(cursor.getColumnIndex("ZIP_CODE_BUSINESS")));
					obj.put("addressBusiness", cursor.getString(cursor.getColumnIndex("ADDRESS_BUSINESS")));
					obj.put("eksternal", cursor.getString(cursor.getColumnIndex("EKSTERNAL")));
					obj.put("referensi", cursor.getString(cursor.getColumnIndex("REFERENSI")));					
					obj.put("avgExpense", cursor.getLong(cursor.getColumnIndex("AVG_EXPENSE")));
					obj.put("dateOfBirth", cursor.getString(cursor.getColumnIndex("DATE_OF_BIRTH")));
					obj.put("maritalStatus", cursor.getString(cursor.getColumnIndex("MARITAL_STATUS")));
					obj.put("spouseName", cursor.getString(cursor.getColumnIndex("SPOUSE_NAME")));
					obj.put("jmlTanggungan", cursor.getLong(cursor.getColumnIndex("JML_TANGGUNGAN")));
					obj.put("productCode", cursor.getString(cursor.getColumnIndex("PRODUCT_CODE")));
					obj.put("ktpNo", cursor.getString(cursor.getColumnIndex("KTP_NO")));
					obj.put("ktpName", cursor.getString(cursor.getColumnIndex("KTP_NAME")));
					obj.put("ktpAddress", cursor.getString(cursor.getColumnIndex("KTP_ADDRESS")));	
					obj.put("entryBy", cursor.getString(cursor.getColumnIndex("ENTRY_BY")));
					obj.put("entryDate", cursor.getString(cursor.getColumnIndex("ENTRY_DATE")));
					obj.put("updateBy", cursor.getString(cursor.getColumnIndex("UPDATE_BY")));
					obj.put("updateDate", cursor.getString(cursor.getColumnIndex("UPDATE_DATE")));
					obj.put("aoCode", cursor.getString(cursor.getColumnIndex("AO_CODE")));
					obj.put("unitCode", cursor.getString(cursor.getColumnIndex("UNIT_CODE")));
					obj.put("progressStatus", cursor.getString(cursor.getColumnIndex("PROGRESS_STATUS")));
					obj.put("umDecision", cursor.getString(cursor.getColumnIndex("UM_DECISION")));
					obj.put("umDecisionNote", cursor.getString(cursor.getColumnIndex("UM_DECISION_NOTE")));
					obj.put("umDecisionDate", cursor.getString(cursor.getColumnIndex("UM_DECISION_DATE")));					
					obj.put("reputasiDebitor", cursor.getString(cursor.getColumnIndex("REPUTASI_DEBITUR")));
					obj.put("coAssigned", cursor.getString(cursor.getColumnIndex("CO_ASSIGNED")));
					obj.put("alternateFor", cursor.getString(cursor.getColumnIndex("ALTERNATE_FOR")));
					obj.put("notInterestedReason", cursor.getString(cursor.getColumnIndex("NOT_INTERESTED_REASON")));
					obj.put("guCloseDeal", cursor.getString(cursor.getColumnIndex("GU_CLOSE_DEAL")));					
					obj.put("isOfflineEntry", cursor.getString(cursor.getColumnIndex("IS_OFFLINE_ENTRY")));
					obj.put("loanNumber", cursor.getString(cursor.getColumnIndex("LOAN_NUMBER")));
					obj.put("CIFNumber", cursor.getInt(cursor.getColumnIndex("CIF_NUMBER")));
					obj.put("omzet1", cursor.getLong(cursor.getColumnIndex("OMZET_1")));
					obj.put("omzet2", cursor.getLong(cursor.getColumnIndex("OMZET_2")));
					obj.put("omzet3", cursor.getLong(cursor.getColumnIndex("OMZET_3")));
					obj.put("omzet4", cursor.getLong(cursor.getColumnIndex("OMZET_4")));
					obj.put("omzet5", cursor.getLong(cursor.getColumnIndex("OMZET_5")));
					obj.put("omzet6", cursor.getLong(cursor.getColumnIndex("OMZET_6")));
					obj.put("omzet7", cursor.getLong(cursor.getColumnIndex("OMZET_7")));
					obj.put("omzet8", cursor.getLong(cursor.getColumnIndex("OMZET_8")));
					obj.put("omzet9", cursor.getLong(cursor.getColumnIndex("OMZET_9")));
					obj.put("omzet10", cursor.getLong(cursor.getColumnIndex("OMZET_10")));
					obj.put("omzet11", cursor.getLong(cursor.getColumnIndex("OMZET_11")));
					obj.put("omzet12", cursor.getLong(cursor.getColumnIndex("OMZET_12")));
					obj.put("omzetAverage", cursor.getLong(cursor.getColumnIndex("OMZET_AVERAGE")));
					obj.put("isDeleted", cursor.getString(cursor.getColumnIndex("IS_DELETED")));
					obj.put("pipelineStartTime", cursor.getString(cursor.getColumnIndex("PIPELINE_START_TIME")));
					obj.put("pipelineFinishTime", cursor.getString(cursor.getColumnIndex("PIPELINE_FINISH_TIME")));
					obj.put("prospectStartTime", cursor.getString(cursor.getColumnIndex("PROSPECT_START_TIME")));
					obj.put("prospectFinishTime", cursor.getString(cursor.getColumnIndex("PROSPECT_FINISH_TIME")));
					obj.put("isPipelineKP", cursor.getString(cursor.getColumnIndex("IS_PIPELINE_KP")));
					obj.put("guFup", cursor.getString(cursor.getColumnIndex("GU_FUP")));
					obj.put("sourceCode", cursor.getString(cursor.getColumnIndex("SOURCE_CODE")));
					obj.put("flagFreeze", cursor.getInt(cursor.getColumnIndex("FLAG_FREEZE")));
					obj.put("placeOfBirth", cursor.getString(cursor.getColumnIndex("PLACE_OF_BIRTH")));
					obj.put("nip", cursor.getString(cursor.getColumnIndex("NIP")));
					obj.put("karakter", cursor.getString(cursor.getColumnIndex("KARAKTER")));
					
					list.add(obj);
					i++;
					
					if (i == App.MAX_ROW_UPLOAD) {												
						UpdateStatusProspect(list);				
						
						int progress = (int)(50 * ((float)numStep/length));						
						publishProgress(progress);						
												
						i = 0;
						numStep++;
						list.clear();						
					}						
				} while (cursor.moveToNext());
				
				if (numStep == step) {
					UpdateStatusProspect(list);									
				}
			}
			cursor.close();		
			
			DSARDB dsar = new DSARDB(_db);
			cursor = dsar.getListUpload(_user.getAoCode());
			list = new ArrayList<JSONObject>();		
			if (cursor.moveToFirst()) {
				int length = cursor.getCount();
				int step = (int)Math.ceil((double)(length/App.MAX_ROW_UPLOAD));
				
				int numStep = 1;				
				int i = 0;
				do {				
					JSONObject obj = new JSONObject();	
					obj.put("prospectID", cursor.getString(cursor.getColumnIndex("PROSPECT_ID")));
					obj.put("visitNo", cursor.getInt(cursor.getColumnIndex("VISIT_NO")));
					obj.put("dateVisitPlan", cursor.getString(cursor.getColumnIndex("DATE_VISIT_PLAN")));
					obj.put("dateVisitActual", cursor.getString(cursor.getColumnIndex("DATE_VISIT_ACTUAL")));
					obj.put("joinFieldWork", cursor.getLong(cursor.getColumnIndex("JOIN_FIELD_WORK")));
					obj.put("objectiveOfVisit", cursor.getString(cursor.getColumnIndex("OBJECTIVE_OF_VISIT")));
					obj.put("resultOfVisit", cursor.getString(cursor.getColumnIndex("RESULT_OF_VISIT")));
					obj.put("remark", cursor.getString(cursor.getColumnIndex("REMARK")));
					obj.put("entryBy", cursor.getString(cursor.getColumnIndex("ENTRY_BY")));
					obj.put("entryDate", cursor.getString(cursor.getColumnIndex("ENTRY_DATE")));
					obj.put("updateBy", cursor.getString(cursor.getColumnIndex("UPDATE_BY")));
					obj.put("updateDate", cursor.getString(cursor.getColumnIndex("UPDATE_DATE")));
					obj.put("isDeleted", cursor.getString(cursor.getColumnIndex("IS_DELETED")));
															
					list.add(obj);
					i++;
					
					if (i == App.MAX_ROW_UPLOAD) {												
						UpdateStatusProspectVisit(list);				
						
						int progress = 50+ (int)(50 * ((float)numStep/length));						
						publishProgress(progress);						
												
						i = 0;
						numStep++;
						list.clear();						
					}						
				} while (cursor.moveToNext());
				
				if (numStep == step) {
					UpdateStatusProspectVisit(list);									
				}
			}
			cursor.close();
			
			ProspectProgressDB pp = new ProspectProgressDB(_db);
			cursor = pp.getListUpload(_user.getAoCode());
			list = new ArrayList<JSONObject>();		
			if (cursor.moveToFirst()) {
				int length = cursor.getCount();
				int step = (int)Math.ceil((double)(length/App.MAX_ROW_UPLOAD));
				
				int numStep = 1;				
				int i = 0;
				do {				
					JSONObject obj = new JSONObject();	
					obj.put("prospectID", cursor.getString(cursor.getColumnIndex("PROSPECT_ID")));
					obj.put("progressStatus", cursor.getString(cursor.getColumnIndex("PROGRESS_STATUS")));					
					obj.put("entryBy", cursor.getString(cursor.getColumnIndex("ENTRY_BY")));
					obj.put("entryDate", cursor.getString(cursor.getColumnIndex("ENTRY_DATE")));
					obj.put("updateBy", cursor.getString(cursor.getColumnIndex("UPDATE_BY")));
					obj.put("updateDate", cursor.getString(cursor.getColumnIndex("UPDATE_DATE")));
															
					list.add(obj);
					i++;
					
					if (i == App.MAX_ROW_UPLOAD) {												
						UpdateStatusProspectProgress(list);				
						
						int progress = 50+ (int)(50 * ((float)numStep/length));						
						publishProgress(progress);						
												
						i = 0;
						numStep++;
						list.clear();						
					}						
				} while (cursor.moveToNext());
				
				if (numStep == step) {
					UpdateStatusProspectProgress(list);									
				}
			}
			cursor.close();
			
			publishStatus("Done!");
			publishProgress(0);
			return new AsyncTaskResult<Void>((Void) null);
		} catch (WSException we) {
			we.printStackTrace();
			publishStatus(we.getMessage());
			publishProgress(0);
			return new AsyncTaskResult<Void>(we);
		} catch (Exception e) {
			Log.e("Download", e.getMessage(), e);
			if (e.getMessage().contains("Unable to resolve") || e.getMessage().contains("failed to connect")) {
				publishStatus("Tidak dapat tersambung ke server");
			} else {
				publishStatus(e.getMessage());
			}
			publishProgress(0);
			return new AsyncTaskResult<Void>(e);
		}		
	}
	
	private void UpdateStatusProspect(ArrayList<JSONObject> list) throws Exception {
		JSONArray jsonArray =  Upload(list, "UploadProspect");
		SQLiteDatabase sqlite = _db.getWritableDatabase();
		int arrayLength = jsonArray.length();						
		for (int z = 0; z < arrayLength; z++) {
			String successId = jsonArray.getString(z);
			ProspectDB.updateUpload(sqlite, successId, _user.getNip());					
		}	
	}
	
	private void UpdateStatusProspectVisit(ArrayList<JSONObject> list) throws Exception {
		JSONArray jsonArray =  Upload(list, "UploadProspectVisit");
		SQLiteDatabase sqlite = _db.getWritableDatabase();
		int arrayLength = jsonArray.length();						
		for (int z = 0; z < arrayLength; z++) {
			String[] successId = jsonArray.getString(z).split("~");			
			DSARDB.updateUpload(sqlite, successId[0], Integer.parseInt(successId[1]), _user.getNip());					
		}	
	}
	
	private void UpdateStatusProspectProgress(ArrayList<JSONObject> list) throws Exception {
		JSONArray jsonArray =  Upload(list, "UploadProspectProgress");
		SQLiteDatabase sqlite = _db.getWritableDatabase();
		int arrayLength = jsonArray.length();						
		for (int z = 0; z < arrayLength; z++) {
			String[] successId = jsonArray.getString(z).split("~");	
			String id = successId[0];
			String pro = "";
			if (successId.length == 2)
				pro = successId[1];
			
			ProspectProgressDB.updateUpload(sqlite, id, pro, _user.getNip());							
		}	
	}

	@Override
	public String getTitle() {
		return "Prospect";
	}
	
	@Override
	protected void onPostExecute(AsyncTaskResult<Void> result) {		
		super.onPostExecute(result);
		
		_notify.notifyFinish(result.getError());
	}
}
